﻿using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System;
using System.Runtime.CompilerServices;

namespace BCVP.Net8.Common.Option.Core;

/// <summary>
/// 配置选项(Options)注入的静态工具类
/// 主要功能是将配置系统中的配置节绑定到强类型的选项类并注入到依赖注入容器中
/// </summary>
public static class ConfigurableOptions
{
    //internal static IConfiguration _configuration;
    ///// <summary>
    ///// 用于初始化静态配置对象_configuration
    ///// </summary>
    ///// <param name="configuration"></param>
    //public static void  ConfigureApplication(this IConfiguration configuration)
    //{
    //    _configuration = configuration;
    //}


    /// <summary>添加选项配置</summary>
    /// <typeparam name="TOptions">选项类型</typeparam>
    /// <param name="services">服务集合</param>
    /// <returns>服务集合</returns>
    public static IServiceCollection AddConfigurableOptions<TOptions>(this IServiceCollection services)
        where TOptions : class, IConfigurableOptions
    {
        Type optionsType = typeof(TOptions);
        string path = GetConfigurationPath(optionsType);
        services.Configure<TOptions>(App.Configuration.GetSection(path));

        return services;
    }

    public static IServiceCollection AddConfigurableOptions(this IServiceCollection services, Type type)
    {
        // 获取配置路径
        string path = GetConfigurationPath(type);
        var config = App.Configuration.GetSection(path);

        // 动态创建选项相关类型
        Type iOptionsChangeTokenSource = typeof(IOptionsChangeTokenSource<>);
        Type iConfigureOptions = typeof(IConfigureOptions<>);
        Type configurationChangeTokenSource = typeof(ConfigurationChangeTokenSource<>);
        Type namedConfigureFromConfigurationOptions = typeof(NamedConfigureFromConfigurationOptions<>);
        iOptionsChangeTokenSource = iOptionsChangeTokenSource.MakeGenericType(type);
        iConfigureOptions = iConfigureOptions.MakeGenericType(type);
        configurationChangeTokenSource = configurationChangeTokenSource.MakeGenericType(type);
        namedConfigureFromConfigurationOptions = namedConfigureFromConfigurationOptions.MakeGenericType(type);

        //注册服务
        services.AddOptions();
        services.AddSingleton(iOptionsChangeTokenSource,
            Activator.CreateInstance(configurationChangeTokenSource, Options.DefaultName, config) ?? throw new InvalidOperationException());
        return services.AddSingleton(iConfigureOptions,
            Activator.CreateInstance(namedConfigureFromConfigurationOptions, Options.DefaultName, config) ?? throw new InvalidOperationException());
    }

    /// <summary>获取配置路径</summary>
    /// 规则：如果类名以"Option"或"Options"结尾，则去掉这部分作为配置路径
    /// <param name="optionsType">选项类型</param>
    /// <returns></returns>
    public static string GetConfigurationPath(Type optionsType)
    {
        var endPath = new[] {"Option", "Options"};
        var configurationPath = optionsType.Name;
        foreach (var s in endPath)
        {
            if (configurationPath.EndsWith(s))
            {
                return configurationPath[..^s.Length];
            }
        }

        return configurationPath;
    }
}